package com.djx.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.jupiter.api.Test;

//https://www.bilibili.com/video/BV1M741137qY?p=60

public class CuratorLock {

    static String MYIP = "192.168.15.132:2181";
    static String MYIPS = "192.168.15.132:2181,192.168.15.132:2182,192.168.15.132:2183";
    static int TIMEOUT = 9000;
    CuratorFramework curatorFramework;

    /**
     * 创建curator 连接zookeeper
     */
    public void connection() {
        ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);
        curatorFramework = CuratorFrameworkFactory.builder()    //创建连接对象
                .connectString(MYIPS)  //IP地址和端口号
                .sessionTimeoutMs(TIMEOUT) //客户端与服务器端会话超时时间
                .retryPolicy(exponentialBackoffRetry)
                //(命名空间)当我们通过连接对象去进行一系列操作时 他是以create作为父节点来操作的 如果不指定  那么久在根节点下创建
//                .namespace("create")
                .build();//构建连接对象
        curatorFramework.start();//打开链接
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (curatorFramework.isStarted() == true) {
            System.out.println("链接YES打开!!!");
        } else {
            System.out.println("链接NO打开!!!");
        }

    }

    /**
     * 排它锁(互斥锁)
     * 当两个互斥锁对象指向同一个路径时,这个两个对象是持有同一把锁的(代码执行过程中是有排他性的)
     */
    @Test
    public void exclusiveLock01() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        connection();
        InterProcessMutex interProcessMutex = new InterProcessMutex(curatorFramework, "/one");
        System.out.println("等待获取锁对象!!!");
        try {
            interProcessMutex.acquire();//获取锁
            for (int i = 0; i < 10; i++) {
                Thread.sleep(3000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();//释放锁
            System.out.println("释放锁!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Test
    public void exclusiveLock02() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        connection();
        InterProcessMutex interProcessMutex = new InterProcessMutex(curatorFramework, "/one");
        System.out.println("等待获取锁对象!!!");
        try {
            interProcessMutex.acquire();//获取锁
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();//释放锁
            System.out.println("释放锁!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 读锁  可以多个进程同时访问一个资源
     */
    @Test
    public void readLock01() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        try {
            connection();
            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(curatorFramework, "/one");
            InterProcessMutex interProcessMutex = lock.readLock();
            interProcessMutex.acquire();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 读锁  可以多个进程同时访问一个资源
     */
    @Test
    public void readLock02() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        try {
            connection();
            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(curatorFramework, "/one");
            InterProcessMutex interProcessMutex = lock.readLock();
            interProcessMutex.acquire();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //********************************************写锁*************************************************************

    /**
     * 写锁 不可以多个进程访问一个资源只能一个个来
     */
    @Test
    public void writeLock01() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        try {
            connection();
            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(curatorFramework, "/one");
            InterProcessMutex interProcessMutex = lock.writeLock();
            interProcessMutex.acquire();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 写锁 不可以多个进程访问一个资源只能一个个来
     */
    @Test
    public void writeLock02() {
        //arg1 连接对象
        //arg2 节点路径exclusive
        try {
            connection();
            InterProcessReadWriteLock lock = new InterProcessReadWriteLock(curatorFramework, "/one");
            InterProcessMutex interProcessMutex = lock.writeLock();
            interProcessMutex.acquire();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(5000);
                System.out.println("i为:::" + i);
            }
            interProcessMutex.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
